﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NeurOthello.NNetwork;

namespace NeurOthello.Logic
{
    public class PlayerSettings
    {
        public int TDLimit { get; set; }
        public int Depth { get; set; }
        public int HiddenN { get; set; }
        public double Lambda { get; set; }
        public bool IsCpu { get; set; }
        public NNetwork.Network Network { get; set; }
        private double exploration;
        public double Exploration { get { return (ExpHL > 0) ? HalfLife(exploration, ExpHL, Time) 
            : exploration; } set { exploration = value; } }
        public int ExpHL { get; set; }
        private double learning;
        public double Learning { get { return (LernHL > 0) ? HalfLife(learning, LernHL, Time) 
            : learning; } set { learning = value; } }
        public int LernHL { get; set; }
        public bool SelfTraining { get; set; }
        public int Time { get; set; }

        private static Random rand = new Random();

        public PlayerSettings(int tdLimit, double lambda, double exploration, double learning)
        {
            TDLimit = tdLimit;
            Lambda = lambda;
            Exploration = exploration;
            Learning = learning;
        }

        public PlayerSettings() 
        {
            TDLimit = 4;
            Depth = 1;
            HiddenN = 80;
            Lambda = 0.5;
            IsCpu = false;
            Exploration = 0.7;
            ExpHL = 1000;
            Learning = 0.7;
            LernHL = 1500;
            SelfTraining = false;
            Time = 0;
            Network = Network.LoadNetwork("nyanetwerketplusturn332000.nnt");
        }

        public NetworkMove RandomExploration(NetworkMove[] evaluatedMoves, NetworkMove best)
        {
            if (rand.NextDouble() > Exploration)
                return best;
            else
                return evaluatedMoves[rand.Next(evaluatedMoves.Length)];
        }

        public NetworkMove RandomTopExploration(NetworkMove[] evaluatedMoves, NetworkMove best, int playerId)
        {
            List<NetworkMove> top = new List<NetworkMove>();
            foreach (NetworkMove nm in evaluatedMoves)
            {
                if (nm.Advantage(playerId) + Exploration >= best.Advantage(playerId))
                    top.Add(nm);
            }
            return top[rand.Next(top.Count)];
        }

        public static double HalfLife(double initial, int halflife, int time)
        {
            return initial / (1 + time / halflife);
        }
    }
}
